//
//  FileManager+Tool.swift
//  ltsp
//
//  Created by jyvyi_ios on 2022/6/9.
//

import Foundation

extension FileManager{
    
    /// 路径是否可写入
    /// - Parameter path: 路径
    /// - Returns: ～
    class func isWritable(for path:String) -> Bool{
        
        return FileManager.default.isWritableFile(atPath: path)
    }
    
    /// 目录是否存在
    /// - Parameter path: 路径
    /// - Returns: ～
    class func isExsit(for path:String) -> Bool{
        
        return FileManager.default.fileExists(atPath: path)
    }
    
    /// 创建目录
    /// - Parameter path: 目录路径
    /// - Returns: ~
    @discardableResult class func createDirectory(at path:String) -> Bool{
        guard !self.isExsit(for: path) else {
            return false
        }
        do{
            try self.default.createDirectory(atPath: path, withIntermediateDirectories: true)
            debugPrint("创建目录成功")
            return true
        }
        catch let error{
            debugPrint("创建目录失败",error)
            return false
        }
    }
    /// 路径
    /// - Parameters:
    ///   - directory: ~
    ///   - create: ~
    /// - Returns: ~
    class func FilePath(for directory:FileManager.SearchPathDirectory,create:Bool = false) -> URL?{
        do{
            let url = try FileManager.default.url(for: directory, in: .userDomainMask, appropriateFor: nil, create: create)
            return url
        }
        catch{
            return nil
        }
    }
    
    /// 保存文件路径
    /// - Parameter extraDiretory: 额外目录
    /// - Returns: ～
    class func savePathOfDocuments() -> String{
        
        return NSHomeDirectory() + "/Documents/"
    }
    class func savePathOfTemp() -> String{
        
        return NSHomeDirectory() + "/tmp/"
    }
    /// 写入数据
    /// - Parameters:
    ///   - data: 数据
    ///   - dataName: 数据名称
    ///   - path: 数据的保存地址
    ///   - atomically: ～
    /// - Returns: ～
    class func write<T:FileManagerReadWritable>(data:T,dataName:String?,to path:String,atomically:Bool = true,isUpdate:Bool = true) -> Bool{
        
        debugPrint("写入数据到:",path)
        if !self.isExsit(for: path){
            debugPrint("目录不存在，创建新目录")
            self.createDirectory(at: path)
        }
        var dataPath = path
        if dataName != nil{
            dataPath = dataPath + "/" + dataName!
        }
        //如果需要更新，但是本地已经有数据，则删除原数据
        if self.isExsit(for: dataPath){
            guard isUpdate else {
                debugPrint("写入失败，文件已存在，并且不需要更新!")
                return false
            }
             self.delete(at: dataPath)
            debugPrint("更新本地数据")
        }
        if data is Array<Any> , let nsArr = data as? NSArray{
            return nsArr.write(toFile: dataPath, atomically: atomically)
        }
        else if data is Dictionary<String,Any>,let dictionary = data as? Dictionary<String,Any>{
            
            let nsDictionary = dictionary as NSDictionary
            return nsDictionary.write(toFile: dataPath, atomically: atomically)
        }
        else if data is String , let string = data as? String{
            do{
                try string.write(toFile: dataPath, atomically: atomically, encoding: .utf8)
                return true
            }
            catch{}
        }
        else if data is Data, let data = data as? Data{
            guard let url = URL.init(string: dataPath) else {
                return false
            }
            do{
                try data.write(to: url, options: .atomic)
            }
            catch{}
        }
        return false
    }
    
    /// 删除路径下的文件
    /// - Parameter path: 路径
    /// - Returns: ～
    @discardableResult class func delete(at path:String) -> Bool{
        guard self.isExsit(for: path) else {
            debugPrint("文件不存在，不可删除")
            return false
        }
        do{
            try self.default.removeItem(atPath: path)
            debugPrint("删除成功")
            return true
        }
        catch let error{
            debugPrint("删除失败",error)
            return false
        }
    }
    
    /// 路径下的所有子路径
    /// - Parameter path: 路径
    /// - Returns: ～
    class func subPath(of path:String) -> [String]?{
        debugPrint("🪝读取目录下的子目录",path)
        return self.default.subpaths(atPath: path)
    }
    
    /// 读取路径下的文件
    /// - Parameter path: 路径
    /// - Returns: ～
    class func read<T:FileManagerReadWritable>(at path:String,type:T.Type) -> T?{
        
        guard self.isExsit(for: path) else {
            return nil
        }
        if type == Array<Any>.self{
           
            let fileData = NSArray.init(contentsOfFile: path)
            return fileData as? T
        }
        else if type == Dictionary<String,Any>.self{

            let fileData = NSDictionary.init(contentsOfFile: path) as? T
            return fileData
        }
        else if type == String.self{
            do{
                let fileData = try String.init(contentsOfFile: path)
                return fileData as? T
            }
            catch{}
        }
        
        return nil
    }
    
    /// 读取路径下所有文件
    /// - Parameters:
    ///   - path: 路径
    ///   - type: 文件类型
    /// - Returns: ～
    class func readAll<T:FileManagerReadWritable>(at path:String,type:T.Type) -> [T]{

        var typeArr : [T] = []
        let diretocyEnumerator = self.default.enumerator(atPath: path)
        while let subPath = diretocyEnumerator?.nextObject() as? String{
            let dataPath = path + "/" + subPath
            debugPrint("🪝便利所有下级目录",dataPath)
            guard let data = self.read(at: dataPath, type: type) else {
                continue
            }
            typeArr.append(data)
        }
        return typeArr
    }
}

protocol FileManagerReadWritable {}
extension Dictionary : FileManagerReadWritable{}
extension Array : FileManagerReadWritable{}
extension String : FileManagerReadWritable{}
extension Data : FileManagerReadWritable{}
